package main

// import (
// 	"github.com/astaxie/beego"
// 	"github.com/astaxie/beego/orm"
// 	_ "github.com/lib/pq"
// 	_ "myapp/web/beegoapi/server/docs"
// 	_ "myapp/web/beegoapi/server/routers"
// )

import (
	"crypto/md5"
	"encoding/base64"
	"fmt"
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/context"
	"github.com/astaxie/beego/orm"
	"github.com/fernet/fernet-go"
	_ "github.com/lib/pq"
	"io"
	_ "myapp/web/beegoapi/server/docs"
	_ "myapp/web/beegoapi/server/routers"
	"strings"
	"time"
)

func init() {
	orm.RegisterDataBase("default", "postgres", "postgres://greenerp:guotinghuayuan30301@localhost:5432/beegoapi?sslmode=disable")
}

func main() {
	if beego.RunMode == "dev" {
		beego.DirectoryIndex = true
		beego.StaticDir["/swagger"] = "swagger"
	}

	//存放验证信息MAP
	var authorizationMap = make(map[string]string, 0)

	beego.InsertFilter("/*", beego.BeforeRouter, func(ctx *context.Context) {
		var appKey = "myapp000001"
		//私匙
		var secretKey []*fernet.Key
		//解码私匙
		secret, err := fernet.DecodeKeys("cw_0x689RpI-jtRR7oE8h_eQsKImvJapLeSbXpwF4e4=")
		if err != nil {
			secretKey = nil
		} else {
			secretKey = secret
		}

		//接收header验证信息，类似appKey:time
		headerStr := ctx.Input.Header("Authorization")
		//分割header验证信息
		headers := strings.Split(headerStr, ":")

		if secretKey != nil {
			//对比第一次请求的appKey，然后发送随机码到客户端
			if headers[0] == appKey {
				var token = func() string {
					h := md5.New()
					salt := "xfhge,ck%^7&8888"
					io.WriteString(h, salt+time.Now().String())
					token := fmt.Sprintf("%x", h.Sum(nil))
					return token
				}
				//随机码
				str := token()
				//加密随机码，获取令牌
				toket, err := fernet.EncryptAndSign([]byte(str), secretKey[0])
				if err == nil {
					//令牌base64编码
					base64ToketStr := base64.StdEncoding.EncodeToString(toket)
					//发送给客户端
					ctx.Output.Body([]byte(base64ToketStr))
					//保存随机码和客户端验证信息映射
					authorizationMap[str] = headerStr
				} else {
					ctx.Output.SetStatus(500)
					ctx.Output.Body([]byte("服务器内部错误"))
				}
			} else { //第二次请求
				//解码header验证信息
				toket, err := base64.StdEncoding.DecodeString(headerStr)
				if err == nil {
					//解密
					signData := fernet.VerifyAndDecrypt(toket, 60*time.Second, secretKey)
					if signData == nil {
						ctx.Output.SetStatus(401)
						ctx.Output.Body([]byte("未授权的访问"))
					} else {
						//分割解密信息
						signs := strings.Split(string(signData), ":")
						//对比authorizationMap
						if authorizationMap[signs[0]] != strings.Join(signs[1:], ":") {
							delete(authorizationMap, signs[0])
							ctx.Output.SetStatus(401)
							ctx.Output.Body([]byte("未授权的访问"))
						} else {
							delete(authorizationMap, signs[0])
						}
					}
				} else {
					ctx.Output.SetStatus(500)
					ctx.Output.Body([]byte("服务器内部错误"))
				}
			}
		} else {
			ctx.Output.SetStatus(500)
			ctx.Output.Body([]byte("服务器内部错误"))
		}
	})
	beego.Run()
}
